<?php

namespace app\index\service;

use app\common\job\ConsultingLawyerMatchV2;
use app\common\job\ConsultingRushExp;
use app\common\job\LawyerResponseStatistics;
use app\common\model\Consulting;
use app\common\model\ConsultingMessage;
use app\common\model\Member;
use app\common\model\MemberInfo;
use app\common\service\GatewayClientServer;
use app\common\service\SubscriptionMessageService;
use app\index\dao\MemberDao;
use app\index\traits\MatchRecorderTrait;
use ShidianUtil\Concurrent\Synchronizer;
use think\facade\Config;
use think\facade\Queue;

/**
 * 咨询律师匹配 V2
 * Class ConsultingLawyerMatchV2Service
 * @package app\index\service
 */
class ConsultingLawyerMatchV2Service
{
    use MatchRecorderTrait;

    /**
     * 极速咨询 随机匹配律师
     * @param Consulting $consulting
     * @return void
     */
    public function matchRandom(Consulting $consulting)
    {
        $second = Config::get('consulting.match_second', 5);

        // 进度卡片
        $content = [
            'millisecond' => $second * 1000,
            'str1' => '正在为您优先匹配',
            'str2' => '金牌律师',
        ];
        $message = $this->getMessageSendService()->sendSystemMessage($consulting, 0, ConsultingMessage::PROGRESS, $content);

        $messageId = $message->id;

        // 5秒后删除该消息，并且匹配律师
        $job_data = ['id' => $consulting->id, 'messageId' => $messageId, 'businessType' => $consulting->businessType];
        Queue::later($second, ConsultingLawyerMatchV2::class, $job_data);

    }

    /**
     * 极速咨询 随机匹配律师第2步
     * @param $consultingId
     * @param $messageId
     * @return void
     */
    public function matchRandomStep2($consultingId, $messageId)
    {

        // 删除消息
        $this->getMessageSendService()->deleteMessage($messageId);


        // 咨询
        $consulting = Consulting::where('id', $consultingId)->find();
        if (!$consulting) {
            return;
        }

        $this->matchRandom0($consulting);
    }

    /**
     * 极速咨询 随机匹配律师
     * @param Consulting $consulting
     * @return void
     */
    public function matchRandom0(Consulting $consulting)
    {
        $consultingId = $consulting->id;
        // $matchType = $consulting->matchType;

        // 随机律师
        if (is_test() || $consulting->memberId == '22155') {
            $lawyer = Member::where('phone', '18111111111')
                ->where('status', '1')
                ->find();
        } else {

            $lawyer = $this->getRandLawyer($consulting);
        }

        if (!$lawyer) {
            return;
        }

        $lawyerId = $lawyer->id;

        // 随机匹配过期时间
        $expTime = Config::get('consulting.rand_time');

        // 设置律师
        $success = $this->setLawyer($consultingId, $lawyerId, $expTime);
        if ($success) {
            $consulting->lawyerId = $lawyerId;

            // 记录匹配情况
            $this->recordMatch($lawyerId, $consultingId, Consulting::MATCH_TYPE_RANDOM);

            $this->incMatchTimes($lawyerId);
        }

        // 触发咨询变动事件（更新前端的咨询模型）
        event('ConsultingUpdated', $consulting);

        // 添加任务，指定时间后重新加入抢单池
        $job_data = ['id' => $consulting->id];
        Queue::later($expTime + 3, ConsultingRushExp::class, $job_data);

        // 延迟统计律师咨询数
        $job_data = ['id' => $lawyerId];
        Queue::later($expTime + 10, LawyerResponseStatistics::class, $job_data);


        // 给用户发 律师名片消息
        $content = [
            'id' => $lawyerId
        ];
        $this->getMessageSendService()->sendSystemMessage($consulting, 0, ConsultingMessage::LAWYER, $content);

        // 未提问，就说一句，请输入案情
        if ($consulting->isAsked == 0) {
            // 发送你好消息
            $lawyerInfo = MemberInfo::where('memberId', $lawyerId)->find();
            if ($lawyerInfo) {
                $content = [
                    'text' => '您好，我是' . $lawyerInfo->practicingLawFirm . '的' . $lawyerInfo->realname . '律师，请在下方输入您的问题我将为您一对一进行解答。',
                ];
                $this->getMessageSendService()->sendMemberMessage($consulting, '1', $lawyerId, ConsultingMessage::TEXT, $content);
            }
        }

        $this->lawyerJoinHandle($consulting, $lawyerId, $lawyer, $expTime);

    }


    /**
     * 找律师 指定匹配律师
     * @param Consulting $consulting
     * @return void
     */
    public function matchDesignate(Consulting $consulting)
    {
        $second = Config::get('consulting.match_second', 5);

        // 进度卡片
        $content = [
            'millisecond' => $second * 1000,
            'str1' => '正在为您',
            'str2' => '接入律师',
        ];
        $message = $this->getMessageSendService()->sendSystemMessage($consulting, 0, ConsultingMessage::PROGRESS, $content);

        $messageId = $message->id;

        // 5秒后删除该消息，并且匹配律师
        $job_data = ['id' => $consulting->id, 'messageId' => $messageId, 'businessType' => $consulting->businessType];
        Queue::later($second, ConsultingLawyerMatchV2::class, $job_data);

    }

    /**
     * 找律师 指定匹配律师第2步
     * @param $consultingId
     * @return void
     */
    public function matchDesignateStep2($consultingId, $messageId)
    {

        // 删除消息
        $this->getMessageSendService()->deleteMessage($messageId);


        // 咨询
        $consulting = Consulting::where('id', $consultingId)->find();
        if (!$consulting) {
            return;
        }

        $this->matchDesignate0($consulting);

    }

    /**
     * 找律师 指定匹配律师
     * @param Consulting $consulting
     * @return void
     */
    public function matchDesignate0(Consulting $consulting): void
    {
        $consultingId = $consulting->id;
        $lawyerId = $consulting->lawyerId;
        $matchType = $consulting->matchType;

        // 律师
        $lawyer = Member::where('id', $lawyerId)->find();
        if (!$lawyer) {
            return;
        }

        // 指定匹配过期时间
        $expTime = Config::get('consulting.designate_time');

        // 设置律师
        $success = $this->setLawyer($consultingId, $lawyerId, $expTime);
        if ($success) {
            $consulting->lawyerId = $lawyerId;

            // 记录匹配情况
            $this->recordMatch($lawyerId, $consultingId, Consulting::MATCH_TYPE_DESIGNATE);
        }

        // 触发咨询变动事件（更新前端的咨询模型）
        event('ConsultingUpdated', $consulting);

        // 添加任务，指定时间后重新加入抢单池
        $job_data = ['id' => $consulting->id];
        Queue::later($expTime + 3, ConsultingRushExp::class, $job_data);

        // 延迟统计律师咨询数
        $job_data = ['id' => $lawyerId];
        Queue::later($expTime + 10, LawyerResponseStatistics::class, $job_data);

        $this->lawyerJoinHandle($consulting, $lawyerId, $lawyer, $expTime);

    }

    /**
     * 取消指定的律师
     * @return bool
     */
    public function cancelDesignateLawyer($consultingId)
    {

        $success = false;

        $signature = Consulting::class . $consultingId;
        $this->getSynchronizer()->synchronized($signature, function () use ($consultingId, &$success) {

            $record = Consulting::where('id', $consultingId)->find();

            if (!is_id($record->lawyerId)) {
                return;
            }

            if ($record->rushStatus == 2) {
                return;
            }

            // 接单方式变成 随机匹配
            $record->matchType = Consulting::MATCH_TYPE_RANDOM;
            $record->lawyerId = '0';
            $record->rushTime = '0';
            $record->rushStatus = 0;
            $record->rushExpTime = '0';
            $record->save();

            $success = true;
        });

        return $success;

    }

    /**
     * 设置律师
     * @param $consultingId
     * @param $lawyerId
     * @param $expTime
     * @return bool
     */
    private function setLawyer($consultingId, $lawyerId, $expTime): bool
    {
        $success = false;

        $signature = Consulting::class . $consultingId;
        $this->getSynchronizer()->synchronized($signature, function () use ($consultingId, $lawyerId, $expTime, &$success) {

            $record = Consulting::where('id', $consultingId)->find();

            if (is_id($record->lawyerId) && $record->lawyerId != $lawyerId) {
                return;
            }

            // 已确认的不能重新分配
            if ($record->rushStatus == 2) {
                return;
            }

            $now = time();

            $record->lawyerId = $lawyerId;
            $record->rushTime = $now;
            $record->rushStatus = 1;
            $record->rushExpTime = $now + $expTime;
            $record->rushTimes = $record->rushTimes + 1;
            $record->save();

            $success = true;
        });

        return $success;
    }

    /**
     * 获取随机匹配的律师
     * @param Consulting $consulting
     * @return Member|null
     */
    private function getRandLawyer(Consulting $consulting): ?Member
    {

        // 排除的律师
        $excludedLawyerIds = [];

        // 如果该律师已被分配了同问题下的咨询，那么不匹配他
        if (is_id($consulting->questionId)) {
            $excludedLawyerIds = Consulting::where('questionId', $consulting->questionId)->column('lawyerId');
        }

        // 不匹配测试账号
        $tests = Config::get('member.testAccount', []);

        // 查询一个律师
        return $this->getMemberDao()->findLawyerRand($consulting->cityId, $consulting->provinceId, $excludedLawyerIds, $tests);
    }

    private function getMessageSendService(): MessageSendService
    {
        return app(MessageSendService::class);
    }

    private function getSynchronizer(): Synchronizer
    {
        return app(Synchronizer::class);
    }

    private function getGatewayClientServer(): GatewayClientServer
    {
        return app(GatewayClientServer::class);
    }

    private function getSubscriptionMessageService(): SubscriptionMessageService
    {
        return app(SubscriptionMessageService::class);
    }

    private function getMemberDao(): MemberDao
    {
        return app(MemberDao::class);
    }

    /**
     * 添加律师到咨询后
     * @param Consulting $consulting
     * @param int $lawyerId
     * @param Member $lawyer
     * @return void
     */
    private function lawyerJoinHandle(Consulting $consulting, int $lawyerId, Member $lawyer, $expTime): void
    {

        // 给律师发 默认系统消息
        $content = [
            'icon' => ['url' => image_url('/storage/static/images/icon/icon_msg.png')],
            'templates' => [['type' => 'text', 'red' => '102', 'text' => '您的信息已被加密，请放心输入',]],
        ];
        $this->getMessageSendService()->sendSystemMessage($consulting, $lawyerId, ConsultingMessage::SYSTEM, $content);

        // 律师加入后，更新工作台列表
        $data = [
            'action' => WORKBENCH_UPDATE,
            'data' => [],
        ];
        $this->getGatewayClientServer()->sendToUid($lawyerId, json_encode($data));

        // 律师加入后，更新红点
        $data = [
            'action' => REDDOT,
            'data' => [],
        ];
        $this->getGatewayClientServer()->sendToUid($lawyerId, json_encode($data));


        // 给律师发模板消息
        $pagepath = 'pages/lawyer/lawyer?confirm_id=' . $consulting->id;
        $userName = Member::where('id', $consulting->memberId)->value('nickname');
        $this->getSubscriptionMessageService()->messageFreeConsulting($lawyer->id, $userName, $consulting->ask, time(), $expTime, $pagepath);
    }

}
